home *** CD-ROM | disk | FTP | other *** search
/ Qu.......ke Neue Level / KroGer Software GmbH - Qu_ke.iso / UTILITY / PRG8.ZIP / F_BITMAP.C next >
C/C++ Source or Header  |  1996-03-02  |  10KB  |  358 lines

  1. /*
  2.  * Copyright (C) 1996 by Raphael Quinet.  All rights reserved.
  3.  *
  4.  * Permission to use, copy, modify, and distribute this software and
  5.  * its documentation for any purpose and without fee is hereby
  6.  * granted, provided that the above copyright notice appear in all
  7.  * copies and that both that copyright notice and this permission
  8.  * notice appear in supporting documentation.  If more than a few
  9.  * lines of this code are used in a program which displays a copyright
  10.  * notice or credit notice, the following acknowledgment must also be
  11.  * displayed on the same screen: "This product includes software
  12.  * developed by Raphael Quinet for use in the Quake Editing Utilities
  13.  * project."  THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR
  14.  * IMPLIED WARRANTY.
  15.  *
  16.  * More information about the QEU project can be found on the WWW:
  17.  * "http://www.montefiore.ulg.ac.be/~quinet/games/editing.html" or by
  18.  * mail: Raphael Quinet, 9 rue des Martyrs, B-4550 Nandrin, Belgium.
  19.  */
  20.  
  21. /*
  22.  * F_BITMAP.C - Filters for bitmap file formats.
  23.  */
  24.  
  25. #include "qeu.h"
  26. #include "q_misc.h"
  27. #include "q_files.h"
  28. #include "f_bitmap.h"
  29.  
  30.  
  31. /* ------------------------------------------------------------------------- */
  32. /* --- Routines for 256 colors palettes ------------------------------------ */
  33.  
  34. /*
  35.  * Read an RGB palette (256 * 3 bytes) from a file.
  36.  */
  37. struct RGB *ReadPalette256(FILE *file, UInt32 offset)
  38. {
  39.   struct RGB *palptr;
  40.  
  41.   if (file == NULL)
  42.     return NULL;
  43.   if (fseek(file, offset, SEEK_SET) < 0)
  44.     return NULL;
  45.   palptr = (struct RGB *)QMalloc(256L * (UInt32)sizeof(struct RGB));
  46.   if (ReadBytes(file, palptr, 768L) == FALSE)
  47.     {
  48.       QFree(palptr);
  49.       return NULL;
  50.     }
  51.   return palptr;
  52. }
  53.  
  54.  
  55. /*
  56.  * Save an RGB palette (256 * 3 bytes) to a file.
  57.  * Return the number of bytes written.
  58.  */
  59. UInt32 SavePalette256(FILE *file, struct RGB *palette256)
  60. {
  61.   if (file == NULL || WriteBytes(file, palette256, 768L) == FALSE)
  62.     return 0L;
  63.   return 768L;
  64. }
  65.  
  66.  
  67. /* ------------------------------------------------------------------------- */
  68. /* --- Routines for "flat" bitmaps ----------------------------------------- */
  69.  
  70. /*
  71.  * Create a new, empty bitmap.
  72.  */
  73. BitMap *NewBitMap()
  74. {
  75.   BitMap *bmptr;
  76.  
  77.   bmptr = (BitMap *)QMalloc((UInt32)sizeof(BitMap));
  78.   bmptr->width = 0;
  79.   bmptr->height = 0;
  80.   bmptr->data = NULL;
  81.   return bmptr;
  82. }
  83.  
  84.  
  85. /*
  86.  * Discard a bitmap and free memory.
  87.  */
  88. void FreeBitMap(BitMap *bmptr)
  89. {
  90.   if (bmptr->data != NULL)
  91.     QFree(bmptr->data);
  92.   QFree(bmptr);
  93. }
  94.  
  95.  
  96. /*
  97.  * Read a bitmap from a file (width + height + data).
  98.  */
  99. BitMap *ReadBitMap(FILE *file, UInt32 offset)
  100. {
  101.   BitMap *bmptr;
  102.   UInt32  w, h;
  103.  
  104.   if (file == NULL)
  105.     return NULL;
  106.   bmptr = NewBitMap();
  107.   if ((fseek(file, offset, SEEK_SET) < 0)
  108.       || (ReadInt32(file, &w) == FALSE)
  109.       || (w > 65535L)
  110.       || (w == 0L)
  111.       || (ReadInt32(file, &h) == FALSE)
  112.       || (h > 65535L)
  113.       || (h == 0L))
  114.     {
  115.       FreeBitMap(bmptr);
  116.       return NULL;
  117.     }
  118.   bmptr->width = (UInt16)w;
  119.   bmptr->height = (UInt16)h;
  120.   bmptr->data = (UInt8 huge *)QMalloc(w * h);
  121.   if (ReadBytes(file, bmptr->data, w * h) == FALSE)
  122.     {
  123.       FreeBitMap(bmptr);
  124.       return NULL;
  125.     }
  126.   return bmptr;
  127. }
  128.  
  129.  
  130. /*
  131.  * Read raw bitmap data from a file.  The width and height must be
  132.  * known in advance.
  133.  */
  134. BitMap *ReadRawBitMap(FILE *file, UInt32 offset, UInt16 width, UInt16 height)
  135. {
  136.   BitMap *bmptr;
  137.  
  138.   if (file == NULL)
  139.     return NULL;
  140.   bmptr = NewBitMap();
  141.   if (fseek(file, offset, SEEK_SET) < 0)
  142.     {
  143.       FreeBitMap(bmptr);
  144.       return NULL;
  145.     }
  146.   bmptr->width = width;
  147.   bmptr->height = height;
  148.   bmptr->data = (UInt8 huge *)QMalloc((UInt32)width * (UInt32)height);
  149.   if (ReadBytes(file, bmptr->data, (UInt32)width * (UInt32)height) == FALSE)
  150.     {
  151.       FreeBitMap(bmptr);
  152.       return NULL;
  153.     }
  154.   return bmptr;
  155. }
  156.  
  157.  
  158. /*
  159.  * Save a bitmap to a file (width + height + data).
  160.  * The number of bytes written is returned (0 if an error occured).
  161.  */
  162. UInt32 SaveBitMap(FILE *file, BitMap *bmptr)
  163. {
  164.   UInt32  w, h;
  165.  
  166.   if (file == NULL || bmptr->width == 0 || bmptr->height == 0)
  167.     return 0L;
  168.   w = (UInt32)(bmptr->width);
  169.   h = (UInt32)(bmptr->height);
  170.   if ((WriteInt32(file, &w) == FALSE)
  171.       || (WriteInt32(file, &h) == FALSE)
  172.       || (WriteBytes(file, bmptr->data, w * h) == FALSE))
  173.     return 0L;
  174.   return w * h + 8L;
  175. }
  176.  
  177.  
  178. /*
  179.  * Save raw bitmap data to a file.
  180.  * The number of bytes written is returned (0 if an error occured).
  181.  */
  182. UInt32 SaveRawBitMap(FILE *file, BitMap *bmptr)
  183. {
  184.   if (file == NULL || bmptr->width == 0 || bmptr->height == 0)
  185.     return 0L;
  186.   if (WriteBytes(file, bmptr->data,
  187.          (UInt32)(bmptr->width) * (UInt32)(bmptr->height)) == FALSE)
  188.     return 0L;
  189.   return (UInt32)(bmptr->width) * (UInt32)(bmptr->height);
  190. }
  191.  
  192.  
  193. /*
  194.  * Print the contents of a bitmap in "outf".
  195.  */
  196. void DumpBitMap(FILE *outf, BitMap *bmptr)
  197. {
  198.   UInt16      r, c;
  199.   UInt8 huge *x;
  200.  
  201.   if (outf == NULL || bmptr == NULL)
  202.     return;
  203.   fprintf(outf, "Size = (%u * %u), %lu bytes.\n",
  204.       bmptr->width, bmptr->height,
  205.       (UInt32)(bmptr->width) * (UInt32)(bmptr->height));
  206.   x = bmptr->data;
  207.   for (r = 0; r < bmptr->height; r++)
  208.     {
  209.       for (c = 0; c < bmptr->width; c++)
  210.     fprintf(outf, "%02x ", *x++);
  211.       fprintf(outf, "\n");
  212.     }
  213. }
  214.  
  215. /* ------------------------------------------------------------------------- */
  216. /* --- Routines for PPM files (pbmplus) ------------------------------------ */
  217.  
  218. /*
  219.  * Save a bitmap as a PPM file (raw format, 24 bits per pixel).  See
  220.  * the pbmplus package for more information.  PPM files can be read by
  221.  * XV and other graphics programs and can be converted easily to other
  222.  * formats.
  223.  */
  224. UInt32 SavePPM(FILE *file, BitMap *bmptr, struct RGB *palette256)
  225. {
  226.   char        buf[20];
  227.   UInt32      size;
  228.   UInt16      r, c;
  229.   UInt8 huge *x;
  230.  
  231.   if (file == NULL || bmptr->width == 0 || bmptr->height == 0
  232.       || palette256 == NULL)
  233.     return 0L;
  234.   sprintf(buf, "P6\n%u %u\n255\n", bmptr->width, bmptr->height);
  235.   size = (UInt32)strlen(buf);
  236.   if (WriteBytes(file, buf, size) == FALSE)
  237.     return 0L;
  238.   x = bmptr->data;
  239.   for (r = 0; r < bmptr->height; r++)
  240.     for (c = 0; c < bmptr->width; c++)
  241.       {
  242.     if (WriteBytes(file, &(palette256[*x++]), 3) == FALSE)
  243.       return 0L;
  244.     size += 3L;
  245.       }
  246.   return size;
  247. }
  248.  
  249.  
  250. /* ------------------------------------------------------------------------- */
  251. /* --- Routines for BMP files (MS Windows) --------------------------------- */
  252.  
  253. struct BMPHeader
  254. {
  255.   /* BITMAPFILEHEADER */
  256.   UInt32 bfSize;                /* total size of file */
  257.   UInt16 bfReserved1;           /* always 0 */
  258.   UInt16 bfReserved2;           /* always 0 */
  259.   Int32  bfOffBits;             /* offset to start of bitmap data */
  260.  
  261.   /* BITMAPINFOHEADER */
  262.   UInt32 biSize;                /* size of bitmap header, always 40 here */
  263.   Int32  biWidth;               /* width of the bitmap, in pixels */
  264.   Int32  biHeight;              /* height of the bitmap, in pixels */
  265.   UInt16 biPlanes;              /* number of planes, always 1 */
  266.   UInt16 biBitCount;            /* number of bits per pixel, always 8 here */
  267.   UInt32 biCompression;         /* compression, always 0 here */
  268.   UInt32 biSizeImage;           /* size of the image */
  269.   Int32  biXPelsPerMeter;       /* horizontal resolution */
  270.   Int32  biYPelsPerMeter;       /* vertical resolution */
  271.   UInt32 biClrUsed;             /* number of colors used, always 256 here */
  272.   UInt32 biClrImportant;        /* number of "important" colors */
  273. };
  274.  
  275.  
  276. /*
  277.  * Save a bitmap as a BMP file (no compression, 8 bits per pixel).  This can
  278.  * be read by most Windows programs.  Note that this routine is simplified
  279.  * and will only work for bitmaps with a 256 colors palette.
  280.  */
  281. UInt32 SaveBMP(FILE *file, BitMap *bmptr, struct RGB *palette256)
  282. {
  283.   struct BMPHeader  bmphdr;
  284.   UInt8 huge       *x;
  285.   UInt8 huge       *buffer;
  286.   Int16             r, c;
  287.   UInt16            linesize;
  288.   UInt32            imgsize;
  289.   UInt32            imgoffset;
  290.   int               i;
  291.  
  292.   if (file == NULL || bmptr->width == 0 || bmptr->height == 0
  293.       || palette256 == NULL)
  294.     return 0L;
  295.   linesize = (bmptr->width + 3) & (~3);
  296.   imgsize = (UInt32)linesize * (UInt32)bmptr->height;
  297.   imgoffset = 2L + (UInt32)sizeof(struct BMPHeader) + 1024L;
  298.  
  299.   /* write the BMP header */
  300.   if (WriteBytes(file, "BM", 2L) == FALSE)
  301.     return 0L;
  302.   bmphdr.bfSize          = SwapInt32(imgoffset + imgsize);
  303.   bmphdr.bfReserved1     = 0;
  304.   bmphdr.bfReserved2     = 0;
  305.   bmphdr.bfOffBits       = SwapInt32(imgoffset);
  306.   bmphdr.biSize          = SwapInt32(40L);
  307.   bmphdr.biWidth         = SwapInt32((UInt32)bmptr->width);
  308.   bmphdr.biHeight        = SwapInt32((UInt32)bmptr->height);
  309.   bmphdr.biPlanes        = SwapInt16(1);
  310.   bmphdr.biBitCount      = SwapInt16(8);
  311.   bmphdr.biCompression   = 0L;
  312.   bmphdr.biSizeImage     = SwapInt32(imgsize);
  313.   bmphdr.biXPelsPerMeter = SwapInt32(1181L);  /* 30 dpi - low res */
  314.   bmphdr.biYPelsPerMeter = SwapInt32(1181L);  /* 30 dpi - low res */
  315.   bmphdr.biClrUsed       = SwapInt32(256L);
  316.   bmphdr.biClrImportant  = 0L;
  317.   if (WriteBytes(file, &bmphdr, sizeof(struct BMPHeader)) == FALSE)
  318.     return 0L;
  319.  
  320.   if (linesize < 1024)
  321.     buffer = (UInt8 huge *)QMalloc(1024L);
  322.   else
  323.     buffer = (UInt8 huge *)QMalloc((UInt32)linesize);
  324.  
  325.   /* write the color palette */
  326.   x = buffer;
  327.   for (i = 0; i < 256; i++)
  328.    {
  329.      *x++ = palette256[i].B;
  330.      *x++ = palette256[i].G;
  331.      *x++ = palette256[i].R;
  332.      *x++ = 0;
  333.    }
  334.   if (WriteBytes(file, buffer, 1024L) == FALSE)
  335.     {
  336.       QFree(buffer);
  337.       return 0L;
  338.     }
  339.  
  340.   /* write the bitmap data (from bottom to top) */
  341.   for (r = bmptr->height - 1; r >= 0; r--)
  342.    {
  343.      for (c = 0; c < bmptr->width; c++)
  344.        buffer[c] = bmptr->data[c + bmptr->width * r];
  345.      for(; c < linesize; c++)
  346.        buffer[c] = 0;
  347.      if (WriteBytes(file, buffer, (UInt32)linesize) == FALSE)
  348.        {
  349.      QFree(buffer);
  350.      return 0L;
  351.        }
  352.    }
  353.   QFree(buffer);
  354.   return imgoffset + imgsize;
  355. }
  356.  
  357. /* end of file */
  358.